package com.wksc.framework.impexp.task;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import com.wksc.framework.impexp.bean.BaseImpParam;
import com.wksc.framework.impexp.bean.ImpReturn;
import com.wksc.framework.impexp.bean.ImportService;
import com.wksc.framework.impexp.constants.IEConstants;
import com.wksc.framework.impexp.constants.ImpErr;
import com.wksc.framework.impexp.constants.TaskStat;
import com.wksc.framework.impexp.handler.imp.BaseImpHandler;
import com.wksc.framework.impexp.mode.ModeFactory;
import com.wksc.framework.impexp.result.ImpResult;
import com.wksc.framework.impexp.template.ImpTemplate;
import com.wksc.framework.impexp.thread.TaskManage;
import com.wksc.framework.impexp.util.ClassFactory;
import com.wksc.framework.impexp.util.ImpExpTools;
import jxl.read.biff.BiffException;
import jxl.write.WriteException;

/**
 * <p>
 * Title(文件名): ImpTask.java
 * </p>
 * <p>
 * Description(描述): 导入任务的处理类
 * </p>
 * <p>
 * Copyright(版权): Copyright (c) 2011
 * </p>
 * <p>
 * Company(公司): 成都四方信息技术有限公司
 * </p>
 * <p>
 * CreateTime(生成日期)：2011-10-20下午03:39:35
 * </p>
 * 
 * @author wanglei
 * @version impExp_C13
 */
public class ImpTask extends Task {

	private static final long serialVersionUID = -2874838491249483963L;

	/**
	 * 错误数据的信息,integer为错误数据在原导入文件中的行号, String表示该行数据的错误信息
	 */
	private Map<Integer, String> incorrectInfo = new TreeMap<Integer, String>();

	/**
	 * 导入任务的handler类实例
	 */
	private BaseImpHandler impHandler;

	/**
	 * 保存发送命令单次结果的数组
	 */
	private List<Integer> sendCommandResult;

	/**
	 * 导入任务传给外部逻辑时需要的参数集合对象
	 */
	private BaseImpParam impParam = new BaseImpParam(baseTemplate);

	/**
	 * 继承的构造函数
	 * 
	 * @param impTemplate
	 * @throws ClassNotFoundException
	 *             初始化时设置任务类型时为找到对应Class异常
	 */
	public ImpTask(ImpTemplate impTemplate) throws ClassNotFoundException {
		super(impTemplate);
		// 初始化结果导入任务对象
		this.result = new ImpResult();
	}

	/**
	 * 导入操作的具体业务处理过程
	 */
	@Override
	protected void process() throws InterruptedException, IOException,
			BiffException, WriteException {
		/* ================定义局部变量================ */
		// 计算分多少次进行处理
		int loopTime = 0;
		// 是否是最后一次处理
		boolean isLast = false;
		// 获取导入任务具体的业务处理类
		ImportService service = ClassFactory
				.getService(((ImpTemplate) baseTemplate).getImpService());
		// 暂存单次从文件中读取到的数据数量
		int readNum = 0;
		/* =================定义局部变量================== */

		/* ============ 初始化导入的Modehandler start ================ */
		// 获取导入模式
		//		Mode impMode = ClassFactory.getImpMode();
		ImpTemplate impTemplate = (ImpTemplate) baseTemplate;
		// 根据导入模式获取文件处理类
		impHandler = ModeFactory.getImpModeHandler(
                impTemplate.getImpFileMode(), impTemplate);
		// 将文件的后缀名设进result
		result.setPostfix(impHandler.getPostfix());
		//获取导入文件
		File impFile = ImpExpTools.getImpFile((ImpTemplate) baseTemplate,
                impHandler.getPostfix().toString());
		if (null != impFile) {
			impHandler.setImpFile(impFile);
		} else {
			result.setResultMsg(ClassFactory.getI18n().getFilenotfoundinfo());
			return;
		}

		/* ============ 初始化导入的Modehandler end ================= */

		// 1. 预处理导入文件, 主要验证导入导入文件头信息是否正确,
		if (!preVerify()) {
			return;
		}

		// 加1是为了使得处理次数从1开始
		loopTime = impHandler.getLoopTime();

		for (int i = 1; i <= loopTime; i++) {
			// 检查中断信号
			if (checkInterrupted()) {
				return;
			}

			// 是否是最后一次处理
			if (i == loopTime) {
				isLast = true;
			}

			// 2.分次读取文件数据
			ImpReturn readResult = impHandler.getDividedData(i);
			readNum = readResult.getCorrectData().size(); //
			addToIncorrectInfo(readResult.getIncorrectData());
			//总行数去掉空白行数
			result.setTotalNum(result.getTotalNum()
					- readResult.getBlankLineNum());

			// 如果单次读取到的数量为0并且不是最后一次处理,则跳过此次处理进入下次循环
			if (0 == readNum && !isLast) {
				continue;
			}

			// 检查中断信号
			if (checkInterrupted()) {
				return;
			}

			// 3. 交予外部逻辑进行数据处理
			impParam.setCorrectData(readResult.getCorrectData());
			impParam.setLast(isLast);
			ImpReturn impReturn = service.businessProcess(impParam);
			if (null == impReturn) {
				continue;
			}
			
			/*
			 * 如果业务需要发送配置变更,有以下两种情况需要补发配置变更
			 * 1. 在业务处理过程中取消了任务
			 * 2. 如果是最后一次处理并且返回业务处理结果是无操作时
			 */
			if (IEConstants.ST_ALTER == impReturn.getBusinessType()
					&& ((isLast && IEConstants.NO_OPS == impReturn.getSent())
							|| cancelTask || ClassFactory.getImpExpDao()
							.getQueueSize(this.getBaseTemplate().getFileName(),
									TaskStat.TASK_CANCELLED,TaskStat.TASK_CANCELLING) > 0)) {
				if(!cancelTask){
					TaskManage.cancelTask(this.getBaseTemplate().getFileName()); //通知自己的cancel任务
				}
				impReturn.setSent(service.sendChange());
			}

			// 4. 处理业务处理结果
			if (null != impReturn.getIncorrectData()) {
				((ImpResult) this.result).addupCorrect(readNum
						- impReturn.getIncorrectData().size());
			}

			handleImpReturn(impReturn, isLast);

			// 检查中断信号
			if (checkInterrupted()) {
				return;
			}
		}

		// 5. 处理错误文件
		handleErrorFile();
	}

	@Override
	protected void beforeExit() throws BiffException, WriteException,
			IOException {
		//这里可以执行取消前的一些清理工作
		handleErrorFile();
	}

	/**
	 * 方法描述：导入前的预处理
	 * 未通过预处理返回false
	 * 通过预处理返回true
	 * 
	 * @creator wanglei
	 * @return
	 */
	private boolean preVerify() {
		ImpErr verifyResult = impHandler.preProcess();
		if (ImpErr.CORRECT != verifyResult) {
			dealErrInfo(verifyResult);
			return false;
		} else {
			result.setTotalNum(impHandler.getTotalLineNum());
			return true;
		}
	}

	/**
	 * 方法描述：将导入前预处理的结果设入结果对象中
	 * 
	 * @creator wanglei
	 * @param errInfo
	 */
	private void dealErrInfo(ImpErr errInfo) {
		switch (errInfo) {
		case HEADER_NOT_MATCH:
			result.setResultMsg(ClassFactory.getI18n().getTileErrorInfo());
			break;
		case NO_DATA:
			result.setResultMsg(ClassFactory.getI18n().getFileNoDataInfo());
			break;
		}
	}

	/**
	 * 对业务逻辑处理结果进行处理
	 * 
	 * @param impReturn
	 * @param isLast
	 */
	private void handleImpReturn(ImpReturn impReturn, boolean isLast) {
		// 将结果中的错误数据假如总错误结果列表中
		if (null != impReturn && null != impReturn.getIncorrectData()) {
			addToIncorrectInfo(impReturn.getIncorrectData());
		}

		//储存每次发送命令的结果
		if (null != impReturn
				&& IEConstants.ST_ORDER == impReturn.getBusinessType()) {
			//初始化sendCommandResult数组
			if (null == sendCommandResult) {
				sendCommandResult = new ArrayList<Integer>();
			}
			sendCommandResult.add(impReturn.getSent());
		}

		//最后一次数据完成后的处理
		boolean mark = false;
		if (isLast || cancelTask) {
			mark = true;
		} else if (ClassFactory.getImpExpDao().getQueueSize(
				this.getBaseTemplate().getFileName(), TaskStat.TASK_CANCELLED,TaskStat.TASK_CANCELLING) > 0) {
			mark = true;
			TaskManage.cancelTask(this.getBaseTemplate().getFileName()); //通知自己的cancel任务
		}
		if (mark) {
			// 取结果中的发送配置变更信息
			((ImpResult) this.result).setSocket(impReturn.isSocket());
			((ImpResult) this.result).setBizType(impReturn.getBusinessType());
			((ImpResult) this.result).setSent(handleSent(impReturn));
			((ImpResult) this.result).setTotalErrNum(this.incorrectInfo.size());
		}
	}

	/**
	 * 方法描述：处理发送命令的方法
	 * 如果业务处理类型不为发送命令,则直接返回最后一次处理结果
	 * 如果为发送命令,则将保存的每次处理的结果进行或运算,如果单次处理结果全为false,最后结果才为false
	 * 
	 * @creator wanglei
	 * @param impReturn
	 * @return
	 */
	private int handleSent(ImpReturn impReturn) {
		int result = IEConstants.NO_OPS;
		if (IEConstants.ST_ORDER == impReturn.getBusinessType()) {
			if (sendCommandResult.contains(IEConstants.SUCCEED)) {
				result = IEConstants.SUCCEED;
			} else if (sendCommandResult.contains(IEConstants.FAIL)) {
				result = IEConstants.FAIL;
			}
		} else {
			result = impReturn.getSent();
		}
		return result;
	}

	/**
	 * 将单次处理的错误信息加入到总错误文件Map中
	 * 
	 * @param incorrectInfo
	 */
	private void addToIncorrectInfo(Map<Integer, String> incorrectInfo) {
		if (null != incorrectInfo && 0 != incorrectInfo.size()) {
			this.incorrectInfo.putAll(incorrectInfo);
		}
	}

	/**
	 * 方法描述：处理错误文件
	 * 
	 * @creator wanglei
	 * @throws java.io.IOException
	 * @throws BiffException
	 * @throws WriteException
	 */
	private void handleErrorFile() throws IOException, BiffException,
			WriteException {
		if (null != incorrectInfo && 0 != incorrectInfo.size()) {
			((ImpResult) this.result).setTotalErrNum(this.incorrectInfo.size());
			incorrectInfo.put(0, ClassFactory.getI18n().getErrorReasonInfo());
			impHandler.writeErrInfo(incorrectInfo);
			// 结果中设置有错误文件的标示
			result.setAllCorrect(IEConstants.HAS_WRONG_FILE);
		}
	}

	@Override
	public void cancelTask() {
		ClassFactory.getImpExpDao().updateTaskCurrentState(this,
				TaskStat.TASK_CANCELLED);
		this.cancelTask = true;
		impParam.setCancelTask(true);
	}
}
